/***************************************************************************
 *   This is a part of the NextCAD Web APP.                                *
 *   Copyright (C) AMCAX, All rights reserved.                             *
 ***************************************************************************/

import { PreemptiveTask } from '@amcax/base';
import { Renderer3D, RendererMgr } from '@amcax/renderer';
import { previewer } from '../../module';

export abstract class Interactor {
  objectTypes: string[] = [];
  cmdName: string | null;
  inTrans: boolean = false;
  result: any;
  private readonly taskRunner = new PreemptiveTask();
  constructor({
    cmdName,
    objectTypes,
  }: {
    cmdName: string;
    objectTypes: string[];
  }) {
    this.cmdName = cmdName;
    this.objectTypes = objectTypes;
  }

  // 执行命令的接口，具体命令由子类实现
  abstract craft(params?): Promise<void | any[]>;
  abstract abortCraft(params?): void;
  abstract finishCraft(params?): void;

  async begin() {
    if (this.inTrans) {
      return;
    }

    this.inTrans = true;
  }
  reset() {
    this.inTrans = false;
    this.cmdName = null;
    this.result = null;
  }
  async preview(params?) {
    if (!this.inTrans) {
      return null;
    }
    const task = () => {
      return new Promise(async (resolve, reject) => {
        const result: any = await this.craft();
        if (result) {
          const models =
            await RendererMgr.getRender<Renderer3D>('3d').parsePreviewModels(
              result,
            );
          if (models?.length > 0) {
            previewer.preview(models);
            resolve(true);
          } else {
            console.log('预览模型渲染失败');
            reject(false);
          }
        } else {
          resolve(true);
        }
      });
    };
    // let run = await this.taskRunner.run(task)
    let run = await task();

    return run;
  }

  async abort() {
    if (!this.inTrans) {
      console.warn(
        'Command abort failed, because it is not in transaction. Potential leak of transaction.',
      );
      return;
    }

    let models;
    try {
      this.inTrans = false;
      models = await this.abortCraft();
    } catch (err) {
      this.inTrans = true;
      throw err;
    }
    if (models?.created?.length > 0) {
      // ctx2.scene.updateOnScene(() => models?.created)
    }
    this.clearPriview();
    // this.onDestroy()
    // events.emit(CmdEventName.onHighlightChange)
  }

  async end() {
    if (!this.inTrans) {
      return;
    }

    try {
      this.inTrans = false;
      await this.finishCraft();
    } catch (err) {
      console.log('Command end failed', err);
      this.inTrans = true;
      throw err;
    }
    this.clearPriview();
    // this.onDestroy()
    // events.emit(CmdEventName.onHighlightChange)
  }

  /**
   销毁
   */
  onDestroy() {
    this.result = undefined;
    previewer.clear();
  }

  // clearPriview
  clearPriview() {
    this.result = undefined;
    previewer.clear();
  }
}
